home *** CD-ROM | disk | FTP | other *** search
- /*
- * mkswap.c - set up a linux swap device
- *
- * (C) 1991 Linus Torvalds. This file may be redistributed as per
- * the Linux copyright.
- *
- * (C) 1996 Red Hat Software - Modified by Erik Troan for Red Hat Software
- * still GPLed, of course
- */
-
- /*
- * 20.12.91 - time began. Got VM working yesterday by doing this by hand.
- *
- * Usuage: mkswap [-c] device [size-in-blocks]
- *
- * -c for readablility checking (use it unless you are SURE!)
- *
- * The device may be a block device or a image of one, but this isn't
- * enforced (but it's not much fun on a character device :-).
- *
- * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
- * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995.
- */
-
- #include <errno.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <sys/stat.h>
- #include <unistd.h>
-
- #include <linux/mm.h>
-
- #include "devices.h"
- #include "install.h"
- #include "log.h"
- #include "mkswap.h"
- #include "newt.h"
- #include "windows.h"
-
- #ifndef __linux__
- # define volatile
- #endif
-
- #define TEST_BUFFER_PAGES 8
-
- static int DEV = -1;
- static long PAGES = 0;
- static int check = 0;
- static int badpages = 0;
-
- static long bit_test_and_set (unsigned int *addr, unsigned int nr)
- {
- unsigned int r, m;
-
- addr += nr / (8 * sizeof(int));
- r = *addr;
- m = 1 << (nr & (8 * sizeof(int) - 1));
- *addr = r | m;
- return (r & m) != 0;
- }
-
- static int bit_test_and_clear (unsigned int *addr, unsigned int nr)
- {
- unsigned int r, m;
-
- addr += nr / (8 * sizeof(int));
- r = *addr;
- m = 1 << (nr & (8 * sizeof(int) - 1));
- *addr = r & ~m;
- return (r & m) != 0;
- }
-
- static int check_blocks(int * signature_page, char * file)
- {
- unsigned int current_page;
- int do_seek = 1;
- static char buffer[PAGE_SIZE];
- newtComponent form = NULL, scale = NULL;
-
- if (check) {
- newtOpenWindow(10, 10, 60, 5, "Formatting");
-
- form = newtForm(NULL, NULL, 0);
-
- sprintf(buffer, "Formatting swap space on device %s...", file);
- newtFormAddComponent(form, newtLabel(1, 1, buffer));
- scale = newtScale(1, 3, 58, PAGES);
- newtFormAddComponent(form, scale);
- newtDrawForm(form);
- newtRefresh();
- }
-
- current_page = 0;
- while (current_page < PAGES) {
- if (!check) {
- bit_test_and_set(signature_page,current_page++);
- continue;
- }
-
- newtScaleSet(scale, current_page);
- newtRefresh();
-
- if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) !=
- current_page*PAGE_SIZE) {
- logMessage("mkswap: seek failed in check_blocks");
- return INST_ERROR;
- }
- if ((do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE)))) {
- bit_test_and_clear(signature_page,current_page++);
- badpages++;
- continue;
- }
- bit_test_and_set(signature_page,current_page++);
- }
- if (badpages)
- logMessage("\t%d bad page%s\n",badpages,(badpages>1)?"s":"");
-
- if (check) {
- newtPopWindow();
- newtFormDestroy(form);
- }
-
- return 0;
- }
-
- static long valid_offset (int fd, int offset)
- {
- char ch;
-
- if (lseek (fd, offset, 0) < 0)
- return 0;
- if (read (fd, &ch, 1) < 1)
- return 0;
- return 1;
- }
-
- static int count_blocks (int fd)
- {
- int high, low;
-
- low = 0;
- for (high = 1; valid_offset (fd, high); high *= 2)
- low = high;
- while (low < high - 1)
- {
- const int mid = (low + high) / 2;
-
- if (valid_offset (fd, mid))
- low = mid;
- else
- high = mid;
- }
- valid_offset (fd, 0);
- return (low + 1);
- }
-
- static int get_size(const char *file, long int * sizeptr)
- {
- int fd;
- int size;
-
- fd = open(file, O_RDWR);
- if (fd < 0) {
- logMessage("mkswap: failed to get size of device %s", file);
- return INST_ERROR;
- }
- if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
- close(fd);
- *sizeptr = size * 512;
- return 0;
- }
-
- *sizeptr = count_blocks(fd);
- close(fd);
-
- return 0;;
- }
-
- int enableswap(char * device_name, int size, int checkBlocks) {
- struct stat statbuf;
- int goodpages;
- int signature_page[PAGE_SIZE/sizeof(int)];
- char devicefile[100];
-
- check = checkBlocks;
-
- if (testing) {
- messageWindow("Testing", "I would make and enable swap on %s",
- device_name);
- return 0;
- }
-
- memset(signature_page,0,PAGE_SIZE);
-
- if (*device_name == '/') {
- strcpy(devicefile, device_name);
- } else {
- sprintf(devicefile, "/tmp/%s", device_name);
- if (devMakeInode(device_name, devicefile)) {
- return INST_ERROR;
- }
- }
-
- if (size)
- PAGES = size;
- else {
- if (get_size(devicefile, &PAGES)) {
- unlink(devicefile);
- return INST_ERROR;
- }
-
- PAGES = PAGES / PAGE_SIZE;
- }
-
- if (PAGES<10) {
- logMessage("mkswap: error: swap area needs to be at least "
- "%ldkB", 10 * PAGE_SIZE / 1024);
- unlink(devicefile);
- return INST_ERROR;
- }
-
- if (PAGES > 8 * (PAGE_SIZE - 10)) {
- PAGES = 8 * (PAGE_SIZE - 10);
- logMessage("mkswap: warning: truncating %s swap to %ldkB",
- device_name, PAGES * PAGE_SIZE / 1024);
- }
-
- DEV = open(devicefile,O_RDWR);
- if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
- logMessage("mkswap: failed to open device: %s\n", device_name);
- unlink(devicefile);
- return INST_ERROR;
- }
- if (!S_ISBLK(statbuf.st_mode))
- check=0;
- else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) {
- logMessage("mkswap: will not try to make swapdevice on '%s'");
- close(DEV);
- unlink(devicefile);
- return INST_ERROR;
- }
-
- if (check_blocks(signature_page, device_name)) {
- close(DEV);
- unlink(devicefile);
- newtPopWindow();
- return INST_ERROR;
- }
-
- if (!bit_test_and_clear(signature_page,0)) {
- logMessage("mkswap: first page unreadable");
- close(DEV);
- unlink(devicefile);
- newtPopWindow();
- return INST_ERROR;
- }
-
- goodpages = PAGES - badpages - 1;
- if (goodpages <= 0) {
- logMessage("mkswap: unable to set up swap-space: unreadable");
- close(DEV);
- unlink(devicefile);
- newtPopWindow();
- return INST_ERROR;
- }
-
- logMessage("setting up swapspace, device = %s, size = %d bytes",
- device_name, goodpages*PAGE_SIZE);
- strncpy((char*)signature_page+PAGE_SIZE-10,"SWAP-SPACE",10);
- if (lseek(DEV, 0, SEEK_SET)) {
- logMessage("mkswap: unable to rewind swap-device");
- close(DEV);
- unlink(devicefile);
- newtPopWindow();
- return INST_ERROR;
- }
-
- if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE)) {
- logMessage("mkswap: unable to write signature page");
- close(DEV);
- unlink(devicefile);
- newtPopWindow();
- return INST_ERROR;
- }
-
- close(DEV);
-
- if (swapon(devicefile)) {
- logMessage("mkswap: swapon() failed: %s\n", strerror(errno));
- }
-
- if (*device_name != '/')
- unlink(devicefile);
-
- return 0;
- }
-